<template>
  <el-form
    ref="ruleFormRef"
    inline
    :rules="rules"
    label-width="100px"
    :model="model"
    v-bind="formAttrs as any"
    :validate-on-rule-change="false"
    @submit.prevent
  >
    <el-form-item v-for="item of displayOptions" :key="item.prop" :prop="item.prop" :label="setDisplayLabel(item.label)">
      <template v-if="item.type === 'cascader'">
        <!-- cascader 有默认插槽无法兼容 -->
        <component
          :is="`el-${item.type}`"
          v-bind="item.attrs"
          :style="setItemStyle(item)"
          v-model="model[item.prop]"
          :placeholder="setPlaceholder(item)"
          @change="allFun(item, 'changeMethod')"
          @input="allFun(item, 'inputMethod')"
        >
        </component>
      </template>
      <component
        v-else
        :is="`el-${item.type}`"
        v-bind="item.attrs"
        :style="setItemStyle(item)"
        v-model="model[item.prop]"
        :placeholder="setPlaceholder(item)"
        @change="allFun(item, 'changeMethod')"
        @input="allFun(item, 'inputMethod')"
        @blur="allFun(item, 'blurFunction')"
        @calendar-change="allFun(item, 'calendarChange')"
      >
        <template v-if="item?.children">
          <component
            :is="`el-${child.type}`"
            v-for="child in item.children"
            :key="child.label"
            :value="child.value"
            :label="child.label"
          />
        </template>
      </component>
    </el-form-item>
    <slot name="formBottom" :scope="model" />

    <div class="flx-justify-end" v-if="saveButton">
      <ElButton @click="cancel">{{ _transitionLanguages('button', 'cancel') }}</ElButton>
      <ElButton type="primary" @click="submitForm()" :loading="loading">
        {{ _transitionLanguages('button', 'save') }}
      </ElButton>
    </div>
  </el-form>
</template>
<script setup lang="ts" name="proForm">
import { optionsProps, FormProps } from '@/components/ProForm/interface';

import type { FormInstance } from 'element-plus';
import { onBeforeMount, computed, ref, CSSProperties } from 'vue';

// 深拷贝
import { cloneDeep } from 'lodash';
import { useGlobalStore } from '@/stores/modules/global';
import { FormWIdthEnum } from '@/enums';
export interface ProFormProps {
  options: optionsProps[];
  visible: boolean;
  formAttrs?: FormProps;
  formCols?: number;
  // 是否显示提交按钮
  saveButton?: boolean;
}
const props = withDefaults(defineProps<ProFormProps>(), {
  options: () => [],
  formCols: 2,
  visible: false,
  saveButton: true
});

const $emit = defineEmits(['getModel', 'cancel', 'update:visible', 'validateForm']);

const globalStore = useGlobalStore();
const ruleFormRef = ref<FormInstance>();

// 语言转换
const _transitionLanguages = (v: string, l: string): string => {
  return transitionLanguages(v, l);
};

const loading = computed(() => globalStore.formLoading);

// 需要显示的表单
const displayOptions = computed(() => props.options.filter(op => !op.hide));

// 验证规则
const rules = computed(() => {
  let r: any = {};
  for (let op of props.options) {
    let rules = cloneDeep(op?.rules || []);
    for (let rs of rules) {
      if (rs.message === op.label || !rs.message) {
        rs.message = transitionLanguages('table', op.label) + isSpacing() + transitionLanguages('rules', 'canNotBeEmpty');
      }
    }
    r[op['prop']] = rules || [];
  }
  return r;
});

let model = ref();

onBeforeMount(() => {
  initForm();
  document.onkeydown = keyupSubmit;
});

const keyupSubmit = (e: KeyboardEvent) => {
  if (e.key === 'Enter') {
    if (!props.visible) {
      return;
    }
    submitForm();
  }
};

const initForm = () => {
  model.value = {};
  for (let op of props.options) {
    const { defaultValue, prop } = op;
    model.value[prop] = defaultValue;
  }
  console.log(model.value, ' model.value');

  // 将字段给到父级 方便后续字段修改
  $emit('getModel', model.value);
};

const cancel = () => {
  $emit('update:visible', false);
  $emit('cancel', false);
};

const submitForm = async () => {
  return new Promise(async resolve => {
    if (!ruleFormRef.value) return;
    await ruleFormRef.value.validate((valid, fields) => {
      if (valid) {
        $emit('validateForm', model.value);
        globalStore.formLoading = true;
        resolve(model.value);
      } else {
        console.log(fields);
        // reject(fields);
      }
    });
  });
};

const allFun = (item: optionsProps, fun: 'changeMethod' | 'inputMethod' | 'calendarChange' | 'blurFunction') => {
  if (typeof item[fun] === 'function') {
    const f: any = item[fun];
    f && f(model);
  }
};

// 设置默认占位符
const setPlaceholder = (item: optionsProps) => {
  let placeholder = item.attrs?.placeholder;

  // 选择类型字段
  const selectTypes = ['select', 'date'];

  const { type, label } = item;

  // 输入框 还是 选择框
  const useType = selectTypes.includes(type) ? 'select' : 'input';
  const p = !placeholder
    ? selectTransitionLanguages(`table`, label, useType)
    : selectTransitionLanguages('placeholder', item.attrs?.placeholder || '', useType);

  return p;
};

// 设置显示的标签
const setDisplayLabel = (label: string) => {
  return transitionLanguages('table', label);
};

// 设置默认 form-item 宽度
const setItemStyle = (item: optionsProps) => {
  const { style } = item.attrs || {};

  let s: CSSProperties = {};

  // 有自定义样式使用自定义样式
  if (style) {
    s = style;
  }

  // 如果没有设置宽度设置默认form-item 宽度
  if (!s.width) {
    const { width } = style || {};
    s.width = width || FormWIdthEnum.itemCol1;
  }

  return s;
};

defineExpose({
  submitForm,
  ruleFormRef
});
</script>
